package Utily

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/gocolly/colly"
	"gopkg.in/ini.v1"
)

type Config struct {
	SkuID  string `ini:"SkuID"`
	Cookie string `ini:"Cookie"`
	Eid    string `ini:"eid"`
	Fp     string `ini:"fp"`
}

type Session struct {
	session       *colly.Collector
	personinfos   PersonInfo
	orderresult   OrderResult
	rid           string
	cookieinit    string
	cookieappend  string
	eid           string
	fp            string
	seckillcookie string
	seckill_url   string
}

func ReadConfigInit() (Config, error) {
	var config Config
	conf, err := ini.Load("test.conf")
	if err != nil {
		log.Println("load config file fail!")
		return config, err
	}
	conf.BlockMode = false
	err = conf.MapTo(&config) //解析成结构体
	if err != nil {
		log.Println("mapto config file fail!")
		return config, err
	}
	return config, nil
}

func RandInt64(min, max int) int {
	if min >= max || min == 0 || max == 0 {
		return max
	}
	return rand.Intn(max-min) + min
}

//初始化
func (c *Session) Init() *colly.Collector {

	c.session = colly.NewCollector()

	c.session.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36"
	//c.session.AllowURLRevisit = true
	config, err := ReadConfigInit()

	if err != nil {
		log.Fatal(err)
	}

	c.cookieinit = config.Cookie
	c.eid = config.Eid
	c.fp = config.Fp

	return c.session
}

func (c *Session) GetCookies(headers *http.Header) string {
	return headers.Get("set-cookie")
}

//步骤1
func (c *Session) GetRequestUrl() {
	c.session = c.Init()
	url := "https://itemko.jd.com/itemShowBtn?skuId=100012043978&from=pc&callback=jQuery" + strconv.Itoa(RandInt64(1000000, 9999999)) + "&_=" + strconv.FormatInt((time.Now().UnixNano()/1e6), 10)
	//print(url + "\n")

	c.session.OnRequest(func(r *colly.Request) {
		r.Headers.Set("Host", "itemko.jd.com")
		r.Headers.Set("cookie", c.cookieinit)
		r.Headers.Set("Referer", "https://item.jd.com/100012043978.html")
		r.Headers.Set("Connection", "keep-alive")
		r.Headers.Set("Accept", "text/html,application/xhtml+xml,application/json,application/xml;q=0.9,image/webp,*/*;q=0.8")
	})

	c.session.OnResponse(func(resp *colly.Response) {
		
		re, _ := regexp.Compile(`sn=(.\w+)`)
		
		s := string(resp.Body)
		if re.MatchString(s) {
			matched := re.FindAllStringSubmatch(s, -1)
			c.seckill_url = "https://marathon.jd.com/captcha.html?skuId=100012043978&sn=" + matched[0][1] + "&from=pc"
			println(c.seckill_url)
			println("步骤1：抢购连接获取成功。。。。。 ")

			c.cookieappend = c.cookieinit + c.GetCookies(resp.Headers)
			//println("设置cookie。。。。。" + c.cookieappend )
		} else {
			println("抢购连接获取。。。。。失败")
		}

	})
	c.session.OnError(func(response *colly.Response, e error) {
		//	fmt.Println("GetRequestUrl")
		fmt.Println(e)
	})

	c.session.Visit(url)
}

//步骤2
func (c *Session) GetKillUrl() {
	c.session = c.Init()
	c.session.OnRequest(func(r *colly.Request) {
		r.Headers.Set("Host", "marathon.jd.com")
		r.Headers.Set("cookie", c.cookieappend)
		r.Headers.Set("Referer", "https://item.jd.com/100012043978.html")
		r.Headers.Set("Connection", "keep-alive")
		r.Headers.Set("Accept", "text/html,application/xhtml+xml,application/json,application/xml;q=0.9,image/webp,*/*;q=0.8")
	})

	c.session.OnResponse(func(resp *colly.Response) {

		c.cookieappend = c.cookieappend + c.GetCookies(resp.Headers)
		fmt.Println("步骤2：设置抢购cookie。。。。。" + c.cookieappend)

	})
	c.session.OnError(func(response *colly.Response, e error) {
		fmt.Println(e)
	})

	c.session.Visit(c.seckill_url)
}

//步骤3
func (c *Session) VisitKillOrderUrl() {
	c.session = c.Init()
	url := "https://marathon.jd.com/seckill/seckill.action?skuId=100012043978&num=1&rid=" + c.rid
	fmt.Println("步骤3")
	c.session.OnRequest(func(r *colly.Request) {
		//fmt.Println("步骤3：cookie:" + c.cookieappend)
		r.Headers.Set("Host", "marathon.jd.com")
		r.Headers.Set("cookie", c.cookieappend)
		r.Headers.Set("Referer", "https://item.jd.com/100012043978.html")
		r.Headers.Set("Connection", "keep-alive")
		r.Headers.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	})
	c.session.OnResponse(func(resp *colly.Response) {
		s := string(resp.Body)
		if strings.Contains(s, "填写订单") {
			fmt.Println("步骤3：进入订单页面。。。。。。。。。成功")

		} else {
			fmt.Println("步骤3：进入订单页面。。。。。。。。。失败")
		}
		c.cookieappend = c.cookieappend + c.GetCookies(resp.Headers)
	})
	c.session.OnError(func(response *colly.Response, e error) {
		fmt.Println(e)
	})

	c.session.Visit(url)
}

//步骤4
func (c *Session) GetInitPerson() {
	c.session = c.Init()
	url := "https://marathon.jd.com/seckillnew/orderService/pc/init.action"

	c.session.OnRequest(func(r *colly.Request) {
		r.Headers.Set("Host", "marathon.jd.com")
		r.Headers.Set("cookie", c.cookieappend)
		r.Headers.Set("content-type", "application/x-www-form-urlencoded")
		r.Headers.Set("Connection", "keep-alive")
		r.Headers.Set("Accept", "application/json,text/plain, text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
		r.Headers.Set("Referer", "https://marathon.jd.com/seckill/seckill.action?skuId=100012043978&num=1&rid="+c.rid)
	})

	c.session.OnResponse(func(resp *colly.Response) {

		s := string(resp.Body)
		if strings.Contains(s, "<") {
			fmt.Println("步骤4：获取秒杀初始化信息失败。。。。。。")
			log.Println(s)

		} else {
			err := json.Unmarshal(resp.Body, &c.personinfos)
			if err != nil {
				fmt.Println(err)
				fmt.Println(string(resp.Body))
			} else {
				fmt.Println("token:" + c.personinfos.Token + "\n")
				fmt.Println("步骤4：获取秒杀初始化信息成功。。。。。。")
				log.Println(s)
			}
		}
		c.cookieappend = c.cookieappend + c.GetCookies(resp.Headers)
	})

	c.session.OnError(func(response *colly.Response, e error) {
		fmt.Println(e)
	})
	c.session.Post(url, map[string]string{
		"sku":             "100012043978",
		"num":             "1",
		"isModifyAddress": "false",
	})
}

func (c *Session) SubmitKill() {
	c.session = c.Init()
	url := "https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action?skuId=100012043978"

	postmap := make(map[string]string)
	type data struct {
		SkuId              string `json:"skuId"`
		Num                string `json:"num"`
		AddressId          string `json:"addressId"`
		YuShou             string `json:"yuShou"`
		IsModifyAddress    string `json:"isModifyAddress"`
		Name               string `json:"name"`
		ProvinceId         string `json:"provinceId"`
		CityId             string `json:"cityId"`
		CountyId           string `json:"countyId"`
		TownId             string `json:"townId"`
		AddressDetail      string `json:"addressDetail"`
		Mobile             string `json:"mobile"`
		Email              string `json:"email"`
		PostCode           string `json:"postCode"`
		InvoiceTitle       string `json:"invoiceTitle"`
		InvoiceCompanyName string `json:"invoiceCompanyName"`
		InvoiceContent     string `json:"invoiceContent"`
		InvoiceTaxpayerNO  string `json:"invoiceTaxpayerNO"`
		InvoiceEmail       string `json:"invoiceEmail"`
		InvoicePhone       string `json:"invoicePhone"`
		InvoicePhoneKey    string `json:"invoicePhoneKey"`
		Invoice            string `json:"invoice"`
		Password           string `json:"password"`
		CodTimeType        string `json:"codTimeType"`
		PaymentType        string `json:"paymentType"`
		AreaCode           string `json:"areaCode"`
		Overseas           string `json:"overseas"`
		Phone              string `json:"phone"`
		Eid                string `json:"eid"`
		Fp                 string `json:"fp"`
		Token              string `json:"token"`
		Pru                string `json:"pru"`
		//	Sk                string `json:"sk"`
	}
	d := &data{
		SkuId:              "100012043978",
		Num:                "1",
		AddressId:          string(c.personinfos.AddressList[0].Id),
		YuShou:             "true",
		IsModifyAddress:    "false",
		Name:               c.personinfos.AddressList[0].Name,
		ProvinceId:         string(c.personinfos.AddressList[0].ProvinceId),
		CityId:             string(c.personinfos.AddressList[0].CityId),
		CountyId:           string(c.personinfos.AddressList[0].CountyId),
		TownId:             string(c.personinfos.AddressList[0].TownId),
		AddressDetail:      c.personinfos.AddressList[0].AddressDetail,
		Mobile:             c.personinfos.AddressList[0].Mobile,
		Email:              "",
		PostCode:           "",
		InvoiceTitle:       "-1",
		InvoiceCompanyName: "",
		InvoiceContent:     "1",
		InvoiceTaxpayerNO:  "",
		InvoiceEmail:       "",
		InvoicePhone:       "",
		InvoicePhoneKey:    "",
		Invoice:            "false",
		Password:           "",
		CodTimeType:        "3",
		PaymentType:        "4",
		AreaCode:           c.personinfos.AddressList[0].AreaCode,
		Overseas:           "0",
		Phone:              "",
		Eid:                c.eid,
		Fp:                 c.fp,
		Token:              c.personinfos.Token,
		Pru:                "",
		//Sk:                "",
	}
	da, err := json.Marshal(d)

	if err != nil {
		fmt.Println(err)
	}

	json.Unmarshal(da, &postmap)
	

	c.session.OnRequest(func(r *colly.Request) {
		// fmt.Println("submit:" + c.cookieappend)
		r.Headers.Set("Host", "marathon.jd.com")
		r.Headers.Set("cookie", c.cookieappend)
		r.Headers.Set("Connection", "keep-alive")
		r.Headers.Set("content-type", "application/x-www-form-urlencoded")
		r.Headers.Set("Accept", "application/json, text/plain, */*")
		r.Headers.Set("Referer", "https://marathon.jd.com/seckill/seckill.action?skuId=100012043978&num=1&rid="+c.rid)

	})
	c.session.OnResponse(func(resp *colly.Response) {

		//var jsonb = []byte(`{"errorMessage":"很遗憾没有抢到，再接再厉哦。","orderId":0,"resultCode":90016,"skuId":0,"success":false}`)
		//var resultOrder interface{}
		// s := string(resp.Body)
		// err:=json.Unmarshal(resp.Body,&resultOrder)
		fmt.Println(string(resp.Body))
		err := json.Unmarshal(resp.Body, &c.orderresult)
		if err != nil {
			fmt.Println("步骤5：下单失败。。。。。。")
			fmt.Println(err)

		} else {
			if c.orderresult.Success {
				fmt.Println("步骤5：下单成功。。。。。。")
			}
			fmt.Println(c.orderresult)
		}
	})
	c.session.OnError(func(response *colly.Response, e error) {
		fmt.Println("err下单失败。。。。。。")
		fmt.Println(e)
	})
	c.session.Post(url, postmap)
}
